package io.renren.modules.avanotes.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.*;
import io.renren.common.vo.input.StudyScheduleIUVo;
import io.renren.common.vo.input.TaskItemVo;
import io.renren.common.vo.output.StudyScheduleOVo;
import io.renren.common.vo.output.StudyScheduleSituationVo;
import io.renren.modules.avanotes.component.MailComponent;
import io.renren.modules.avanotes.component.TimeWheelComponent;
import io.renren.modules.avanotes.dao.FormworkDao;
import io.renren.modules.avanotes.dao.ScheduleSummaryDao;
import io.renren.modules.avanotes.dao.StudyScheduleDao;
import io.renren.modules.avanotes.entity.*;
import io.renren.modules.avanotes.service.*;
import io.renren.modules.sys.dao.SysUserDao;
import io.renren.modules.sys.entity.SysUserEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.EmailException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;


//@Service("studyScheduleService")//默认只有一个实现，那就不写名称了直接使用默认的名称！
@Service
@Slf4j
public class StudyScheduleServiceImpl extends ServiceImpl<StudyScheduleDao, StudyScheduleEntity> implements StudyScheduleService {

    @Value("${role.publishId}")
    String publishRoleId;

    @Autowired
    FormworkDao formworkDao;

    @Autowired
    SysUserDao sysUserDao;

    @Autowired
    ScheduleSummaryDao scheduleSummaryDao;

    @Autowired
    FormworkService formworkService;

    @Autowired
    SpecialSubjectService specialSubjectService;

    @Autowired
    ReferenceMaterialService referenceMaterialService;

    @Autowired
    SpecialSubjectScheduleRelationService specialSubjectScheduleRelationService;

    @Autowired
    FormworkScheduleRelationService fsRelationService;

    @Autowired
    MaterialScheduleRelationService materialScheduleRelationService;

    @Autowired
    TimeWheelComponent timeWheelComponent;

    @Autowired
    MailComponent mailComponent;

    public static final String[] simpleColumnArr = {StudyScheduleEntity.CN_ID, StudyScheduleEntity.CN_NAME};

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<StudyScheduleEntity> page = this.page(
                new Query<StudyScheduleEntity>().getPage(params),
                new QueryWrapper<StudyScheduleEntity>().orderByDesc(StudyScheduleEntity.CN_CREATE_TIME)
        );

        return new PageUtils(page);
    }

    /**
     * 新增计划
     * 业务还挺复杂！
     *
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)//NOTEME 需要主动加上，否则checkException 不会发生
    public long insert(StudyScheduleIUVo vo) throws Exception {
        StudyScheduleEntity entity = new StudyScheduleEntity();
        entity.setType(vo.getType());
        //设置其他参考资料信息
        entity.setMaterialsRemark(vo.getMaterialsRemark());
        //设置主要问题
        entity.setMainProblem(vo.getMainProblem());
        //设置计划执行日期 默认今日，后续补偿
        String todayDate = DateUtils.format(new Date(), DateUtils.DATE_PATTERN_INT);
        //NOTEME:取消原执行日期只为一天的设计
        //entity.setDay(Integer.parseInt(todayDate));
        entity.setStartTime(vo.getStartTime());
        entity.setEndTime(vo.getEndTime());
        if (StringUtils.isBlank(vo.getName())) {
//            if (StringUtils.isBlank(vo.getDate())) {
//                todayDate = DateUtils.format(new Date());
//            } else {
//                todayDate = vo.getDate();
//                //
//                entity.setDay(Integer.parseInt(todayDate.replaceAll("-", "")));
//            }
            //如果名称为空
            entity.setName(todayDate.concat(" 日学习计划"));
        } else {
            //设置默认
            entity.setName(vo.getName());
        }
        //0.先 insert 获取 id
        entity.setStatus(0);
        entity.setUpdateTime(new Date());
        this.save(entity);
        //专题关系
        List<SpecialSubjectScheduleRelationEntity> sssrll = new ArrayList<>();
        //参考资料关系
        List<MaterialScheduleRelationEntity> msrll = new ArrayList<>();
        //模板关系
        List<FormworkScheduleRelationEntity> fsrll = new ArrayList<>();
        //formwork in ids 任务模板中所有转化为id
        List<Integer> fwIds = new ArrayList<>();
        StudyScheduleEntity updater = new StudyScheduleEntity();
        Long mid = entity.getId();
        updater.setId(mid);
        //1.生成专题相关
        List<String> subjects = vo.getSpecialSubjects();
        //保存专题数据
        List<Integer> lastIds = new ArrayList<>();
        String ssStr = "";
//        subjects.stream().map(x -> ssStr.concat(x).concat(";"));
        for (String subject : subjects) {
            ssStr = ssStr.concat(subject).concat(";");
            Integer lastId = Integer.parseInt(subject.substring(subject.lastIndexOf(",") + 1));
            sssrll.add(new SpecialSubjectScheduleRelationEntity(lastId, mid));
            lastIds.add(lastId);
        }
        //添加 联系
        specialSubjectScheduleRelationService.saveBatch(sssrll);
        updater.setSpecialSubjects(ssStr);
        //2.生成模板的联系
        genFormworkRelations2(vo, mid, fwIds);
        //3.生成参考资料的联系
        List<Integer> refMaterialIds = vo.getRefMaterialIds();
        StringBuilder sb = new StringBuilder();
        for (Integer materialId : refMaterialIds) {
            msrll.add(new MaterialScheduleRelationEntity(materialId, mid));
            ReferenceMaterialEntity tempMaterial = referenceMaterialService.getEntity(materialId);
            sb.append(tempMaterial.getTitle()).append("</br>");
        }
        //保存
        materialScheduleRelationService.saveBatch(msrll);
        //4.按照模板生成 content + resources
        //content的模板：任务（分值）</br>...
        //resource的模板：title</br>...
        //content
        updater.setContentHtml(genContentByTaskItems(vo));
        //MaterialsHtml
        updater.setMaterialsHtml(sb.toString());
        //生成专题html(要获取所有的名称)
        //这里只获取最后一个
        //updater.setSpecialSubjectsHtml(genSpecialSubjectsHtmlByIds(lastIds));
        updater.setSpecialSubjectsHtml(vo.getAllLabelPath().replaceAll(";", "</br>"));
        //执行更新
        this.updateById(updater);
        //找到角色，发送邮件！
        //计算时间
        long ts = BizUtils.internalTimeStamp(vo.getTime());
        long seconds = ts / 1000;
        log.info("距离执行还有:{} s", seconds);
        timeWheelComponent.addTask(seconds, () -> {
            List<SysUserEntity> list = sysUserDao.selectUsersByRoleId(Long.parseLong(publishRoleId));
            Set<String> recs = new HashSet<>();
            for (SysUserEntity userEntity : list) {
                recs.add(userEntity.getEmail());
            }
            String sendContent = "主要解决问题".concat(entity.getMainProblem()).concat("</br>专题内容：</br>").concat(updater.getSpecialSubjectsHtml()).concat("</br>计划内容：</br>").concat(updater.getContentHtml()).concat("</br>学习资料：</br>").concat(updater.getMaterialsHtml())
                    .concat("</br>其他参考资料：</br>").concat(entity.getMaterialsRemark());
            //send
            try {
                mailComponent.send(recs, entity.getName(), sendContent);
            } catch (EmailException e) {
                log.error(e.getMessage());
            }
        });
        return updater.getId();
    }

    @Override
    public StudyScheduleOVo getEntityDetailById(Long id) {
        StudyScheduleEntity entity = this.getById(id);
        if (entity == null) {
            return null;
        }
        //获取参考资料
        List<ReferenceMaterialEntity> rList = referenceMaterialService.getListByScheduleId(id);
        StudyScheduleOVo resVo = new StudyScheduleOVo();
        BeanUtils.copyProperties(entity, resVo);
        resVo.setRefMaterialList(rList);
        return resVo;
    }

    @Override
    public List<StudyScheduleEntity> list4SelectByName(String name) {
        List<StudyScheduleEntity> list = this.list(
                new QueryWrapper<StudyScheduleEntity>().select(simpleColumnArr).like(StudyScheduleEntity.CN_NAME, name));
        return list;
    }

    @Override
    public PageUtils listSituationQueryPage(Map<String, Object> params) {
        PageUtils page = this.queryPage(params);
        List<StudyScheduleEntity> list = (List<StudyScheduleEntity>) page.getList();
        List<StudyScheduleSituationVo> resList = new ArrayList<>();
        SysUserEntity userEntity = ShiroUtils.getUserEntity();
        for (StudyScheduleEntity entity : list) {
            Integer count = scheduleSummaryDao.selectCount(new QueryWrapper<ScheduleSummaryEntity>().eq(ScheduleSummaryEntity.CN_SCHEDULE_ID, entity.getId())
                    .eq(ScheduleSummaryEntity.CN_CREATE_USER_ID, userEntity.getUserId()));
            StudyScheduleSituationVo vo = new StudyScheduleSituationVo();
            BeanUtils.copyProperties(entity, vo);
            vo.setHasFinishSummary(count > 0);

            resList.add(vo);
        }
        //
        page.setList(resList);
        return page;
    }


    private String genSpecialSubjectsHtmlByIds(List<Integer> lastIds) throws Exception {
        if (CollectionUtils.isEmpty(lastIds)) {
            return "";
        }
        //查询
        StringBuilder sb = new StringBuilder();
        for (Integer lastId : lastIds) {
            SpecialSubjectEntity entity = specialSubjectService.getEntity(lastId);
            sb.append(entity.getName()).append("</br>");
        }
        return sb.toString();
    }

    /**
     * 根据任务详情生成模板
     *
     * @param vo
     * @return
     * @throws Exception
     */
    private String genContentByTaskItems(StudyScheduleIUVo vo) throws Exception {
        StringBuilder sb = new StringBuilder();
        int index = 1;
        for (TaskItemVo taskItem : vo.getTaskItems()) {
            Integer tempId = 0;
            if (taskItem.getMainId() == null || taskItem.getMainId() == 0) {
                //直接用 id 即可
                tempId = Integer.parseInt(taskItem.getId());
            } else {
                //使用 mainId 即可
                tempId = taskItem.getMainId();
            }
            //获取缓存数据
            FormworkEntity fEntity = formworkService.getEntity(tempId);
            if (fEntity != null) {
                sb.append(index).append(". ").append(fEntity.getName()).append("：").append(taskItem.getScore()).append(" 分").append("</br>");
            }
            index++;
        }
        return sb.toString();
    }

    /**
     * 生成模板的联系（模板是自由的）
     *
     * @param vo
     * @param mid
     * @param fwIds
     */
    private void genFormworkRelations(StudyScheduleIUVo vo, Long mid, List<Integer> fwIds) {
        //新增关系
        List<FormworkScheduleRelationEntity> formRelations = new ArrayList<>();
        //form 关联的IDs
        List<Integer> formRelationIds = new ArrayList<>();
        //等待添加的
        List<FormworkEntity> waitSaveFormList = new ArrayList<>();
        List<TaskItemVo> taskItems = vo.getTaskItems();
        //前端传参的 所有IDs
        List<String> formIds = new ArrayList<>();
        String idsStr = "";
        //Set 为了快速匹配 TaskItemVo
        Map<String, TaskItemVo> taskItemMap = new HashMap<>();
        for (TaskItemVo taskItem : taskItems) {
            formIds.add(taskItem.getId());
            idsStr = idsStr.concat(taskItem.getId()).concat(",");
            //add 2 map
            taskItemMap.put(taskItem.getId(), taskItem);
        }
        //命中的 ID
        List<Integer> inIds = formworkDao.selectIdsByFindInSet(idsStr);
        HashSet<String> set = new HashSet<>();
        inIds.forEach(p -> {
            set.add(p + "");
            formRelationIds.add(p);
        });
        //
        taskItems.forEach(p -> {
            if (!set.contains(p.getId())) {
                FormworkEntity tempEntity = new FormworkEntity(p.getId(), 1);
                waitSaveFormList.add(tempEntity);

            }
        });
        if (!CollectionUtils.isEmpty(waitSaveFormList)) {
            //formworkService.saveBatch(waitSaveFormList);
            formworkService.insertIgnoreBatch(waitSaveFormList);
            waitSaveFormList.forEach(p -> {
                //
                inIds.add(p.getId());
                //补偿到 taskItemMap
                taskItemMap.get(p.getName()).setMainId(p.getId());
            });
        }
        //
        inIds.forEach(p -> {
            formRelations.add(new FormworkScheduleRelationEntity(p, mid));
            //最后返回所有命中的id
            fwIds.add(p);
        });
        //保存关系
        fsRelationService.saveBatch(formRelations);
    }

    /**
     * 前端传参由 直接的String（可能是 id/name） 转为 id,name 字段分开.
     * 执行保存关系 + 返回模板ids
     * 由于能获取到ID，所以就不进行校验了（放弃 FIND_IN_SET）
     *
     * @param vo
     * @param mid
     * @param fwIds 最终模板的所有ID
     */
    private void genFormworkRelations2(StudyScheduleIUVo vo, Long mid, List<Integer> fwIds) {
        //新增关系
        List<FormworkScheduleRelationEntity> formRelations = new ArrayList<>();
        //等待添加的
        List<FormworkEntity> waitSaveFormList = new ArrayList<>();
        //NOTEME 需要将新增的数据回写到 taskItems
        List<TaskItemVo> taskItems = vo.getTaskItems();
        for (TaskItemVo taskItem : taskItems) {
            if (StringUtils.isBlank(taskItem.getId())) {
                //如果为空，作为新数据添加
                waitSaveFormList.add(new FormworkEntity(taskItem.getName(), 1));
            } else {
                fwIds.add(Integer.parseInt(taskItem.getId()));
            }
        }
        //添加新的模板
        if (!CollectionUtils.isEmpty(waitSaveFormList)) {
            //formworkService.saveBatch(waitSaveFormList);
            formworkService.insertIgnoreBatch(waitSaveFormList);
//            int insertIndex = 0;
//            for (FormworkEntity entity :
//                    waitSaveFormList) {
//                //NOTEME 关于如何做到补偿：由于之前的有序遍历，保证了如果存在空缺，那一定是新增的数据的！
//                fwIds.add(entity.getId());
//                while (insertIndex < taskItems.size()) {
//
//                }
//            }
            int tempIndex = 0, tempLen = waitSaveFormList.size();
            //
            for (TaskItemVo taskItem : taskItems) {
                if (StringUtils.isBlank(taskItem.getId())) {
                    //从 fwIds 顺序补充
                    for (int i = tempIndex; i < tempLen; i++) {
                        FormworkEntity tempEntity = waitSaveFormList.get(tempIndex);
                        taskItem.setId(tempEntity.getId() + "");
                        fwIds.add(tempEntity.getId());
                    }
                }
            }
        }
        //添加关系
        for (Integer fwId : fwIds) {
            formRelations.add(new FormworkScheduleRelationEntity(fwId, mid));
        }
        //保存关系
        fsRelationService.saveBatch(formRelations);
    }
}